# -*- coding: utf-8 -*-
import argparse
import logging
import os
import re
import subprocess
import time
from typing import Union, Literal

import conf
from conf import Config
from models.Node import Component

CrawlerLogger = logging.getLogger('crawlerLogger')


def check_and_create_directory () :
    base_path = f"./{conf.LOG_DICTIONARY_NAME}"
    prefixes = ["wx", "zfb", "bd", "kuai"]
    suffixes = ["log", "res", "graph", "record"]

    for prefix in prefixes :
        for suffix in suffixes :
            path = os.path.join(base_path, prefix, suffix)
            if not os.path.isdir(path) :
                os.makedirs(path)

def init_logging(log_level: str, platform: str, applets_name: str):
    check_and_create_directory()
    applets_name = applets_name.replace(":", "-")
    if log_level == "debug":
        level = logging.DEBUG
    else:
        level = logging.INFO

    # 设置 CrawlerLogger 的级别
    CrawlerLogger.setLevel(level)

    # 文件处理器
    file_handler = logging.FileHandler(f"./{conf.LOG_DICTIONARY_NAME}/{platform}/log/{applets_name}.log", 'w')
    file_handler.setLevel(level)
    file_format = "%(asctime)s %(levelname)-5s %(filename)-14s:%(lineno)-4s - %(message)s"
    file_handler.setFormatter(logging.Formatter(file_format, "%Y-%m-%d %H:%M:%S"))

    # 控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    console_handler.setFormatter(logging.Formatter(file_format))

    # 将处理器添加到 CrawlerLogger
    CrawlerLogger.addHandler(file_handler)
    CrawlerLogger.addHandler(console_handler)

def judge_button_is_popups(buttonText: str) -> Literal[True, False]:
    for text in Config.POP_TEXT_KEYWORD:
        if text in buttonText and '登录' not in buttonText:
            return True
    return False

def judge_driver_title_visible(driver_title: str) -> bool:
    return (":VISIBLE" in driver_title)

def set_config(driver):
    # 获取缩放后的 WebView 窗口大小
    scale_window_size = driver.execute_script('return {height: window.innerHeight, width: window.innerWidth};')
    scale_ratio = Config.PHONE_WIDTH / scale_window_size['width']
    actual_window_size = scale_ratio * scale_window_size['height']
    Config.top_bar_height = Config.PHONE_HEIGHT - actual_window_size

def uninstall_appium_app():
    cmd_str = [
        f"adb -s {conf.CLIENT_SIDE_CONF.DEVICE_ID} uninstall io.appium.settings",
        f"adb -s {conf.CLIENT_SIDE_CONF.DEVICE_ID} uninstall io.appium.uiautomator2.server.test",
        f"adb -s {conf.CLIENT_SIDE_CONF.DEVICE_ID} uninstall io.appium.uiautomator2.server"
    ]
    for i in cmd_str:
        os.system(i)

def kill_app(package_Name, device):
   flag = 0
   while flag < 3:
      temp = os.popen('adb -s {} shell am force-stop {}'.format(device, package_Name)).read()
    #   temp = fibonacci_rpc.call('adb -s {} shell am force-stop {}'.format(device, packageName))
      time.sleep(1)
      if 'Error' in str(temp):
         flag += 1
      else:
         break
   if flag != 3:
      CrawlerLogger.info(f"[+] {device}: {package_Name}, 退出成功")
      return True
   else:
      CrawlerLogger.info(f"[+] {device}: {package_Name}, 退出失败")
      return False

def open_app(package_Name, main_activity, device):

   flag = 0
   while flag < 3:
      temp = os.popen('adb -s {} shell am start -W -S -n {}/{}'.format(device, package_Name, main_activity)).read()
    #   temp = fibonacci_rpc.call('adb -s {} shell am start -W -n {}/{}'.format(device, packageName, mainActivity))
      time.sleep(1)
      if 'Error' in str(temp):
         flag += 1
      else:
         break
   if flag != 3:
      CrawlerLogger.info(f"[+] {device}: {package_Name}, 启动成功")
      return True
   else:
      CrawlerLogger.info(f"[+] {device}: {package_Name}, 启动失败")
      return False

def get_top_activity_name():
    if conf.CLIENT_SIDE_CONF.PLATFORM == 'kuai':
        cmd = 'adb -s {} shell "dumpsys activity top | grep ACTIVITY"'.format(conf.CLIENT_SIDE_CONF.DEVICE_ID)
        output = subprocess.check_output(cmd, shell=True, text=True, encoding='utf-8').strip().split("\n")[0]
    else:
        cmd = 'adb -s {} shell "dumpsys activity activities | grep mResumedActivity"'.format(conf.CLIENT_SIDE_CONF.DEVICE_ID)
        output = subprocess.check_output(cmd, shell=True, text=True, encoding='utf-8').strip()

    # 解析输出以获取 Activity 名称
    if output:
        parts = output.split(' ')
        for part in parts:
            if '/' in part:
                return part.split('}')[0].strip()
    return None


def judge_mini_program_is_on_top() -> bool:
    return get_top_activity_name() == conf.CLIENT_SIDE_CONF.APPLET_ACTIVITY_NAME

def find_webview_context () -> Union[str, None] :
    m_resumed_activity = get_top_activity_name()
    if m_resumed_activity and m_resumed_activity[-1].isdigit():
        return m_resumed_activity[-1]
    else:
        return "0"

    # cmd = ['adb', 'shell', 'dumpsys', 'activity', 'top', '|', 'grep', '"ACTIVITY"']
    # result = subprocess.run(cmd, stdout=subprocess.PIPE)
    #
    # if result.returncode == 0 :
    #     outputs = str(result.stdout.decode('utf-8'))
    #     match = re.search(r'AppBrandUI(\d+)', outputs)
    #     if match :
    #         return match.group(1)
    #     else :
    #         match = re.search(r'AppBrandUI', outputs)
    #         if match :
    #             return '0'
    # return '-1'

def judge_mini_program_is_run(driver) -> bool:
    if not judge_mini_program_is_on_top():
        driver.press_keycode(4)
        CrawlerLogger.info("[*] Leave mini program, Back to previous page")
        time.sleep(2)
    return judge_mini_program_is_on_top()

def parse_element(element) -> Union[Component, None]:
    if element.get("class") == "android.widget.Image":
        element_text = "图片"
    else:
        element_text = element.get("text")
    bounds_str = element.get('bounds')
    match = re.match(r'\[(\d+),(\d+)]\[(\d+),(\d+)]', bounds_str)

    if match :
        x1, y1, x2, y2 = map(int, match.groups())
        width, height = x2 - x1, y2 - y1
        if 0 < x1 <= conf.CLIENT_SIDE_CONF.PHONE_WIDTH and \
                0 < y1 <= (conf.CLIENT_SIDE_CONF.PHONE_HEIGHT + 100) \
                and element_text:
            # 创建一个Component对象
            component = Component({
                'rect' : {
                    'x' : x1,
                    'y' : y1,
                    'width' : width,
                    'height' : height,
                },
                'text' : element_text,
                'tagName': element.tag,
                'className': element.get('class')
            })
            return component
        return None
    return None


def str2bool(v):
    if isinstance(v, bool):
       return v
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')

def get_platform_version(device_id):
    try:
        # 执行 adb 命令来获取设备的平台版本
        result = subprocess.run(['adb', '-s', device_id, 'shell', 'getprop', 'ro.build.version.release'],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                text=True)

        # 检查命令是否成功执行
        if result.returncode != 0:
            raise Exception(f"Error: {result.stderr}")

        # 返回平台版本
        return result.stdout.strip()
    except Exception as e:
        CrawlerLogger.debug(f"Get platform version error occurred: {e}")
        return None

def switch_right_input():
    # 列出所有输入法
    cmd = 'adb -s {} shell ime list -s'.format(conf.CLIENT_SIDE_CONF.DEVICE_ID)
    output = subprocess.check_output(cmd, shell=True, text=True, encoding='utf-8').strip()

    for ime in output.split('\n'):
        if ime == 'com.sohu.inputmethod.sogou/.SogouIME':
            cmd = 'adb -s {} shell ime set {}'.format(conf.CLIENT_SIDE_CONF.DEVICE_ID, ime)
            subprocess.check_output(cmd, shell=True, text=True, encoding='utf-8').strip()
            return

    for ime in output.split('\n') :
        if ime != 'io.appium.android.ime/.UnicodeIME' :
            cmd = 'adb -s {} shell ime set {}'.format(conf.CLIENT_SIDE_CONF.DEVICE_ID, ime)
            subprocess.check_output(cmd, shell=True, text=True, encoding='utf-8').strip()
            return
